package svm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

import photo.Photo;
import utils.Logger;
import utils.Utils;
import au.AU;
import au.AU.Label;

public class LuxandDataUtils {
	
	public static void createLuxandData(String image_data_dir) throws Exception {
		createLuxandDataForTraining("luxand_data", image_data_dir, false);
	}

	public static void createLuxandDataForTraining(String output_file_name,
			String image_data_dir, boolean withLabels) throws Exception {

		int imgDone = 0;
		File bosphorusRoot = new File(image_data_dir);
		File output = null;
		ArrayList<String> processed = null;

		// output file - check if exists, create if necessary and load
		// already existing content
		if (withLabels) {
			processed = new ArrayList<String>();
			output = new File(output_file_name);
			if (output.exists()) {
				BufferedReader br = new BufferedReader(new FileReader(output));
				String line;
				while ((line = br.readLine()) != null) {
					if (line.split(":").length == 3)
						processed.add(line.split(":")[0]);
				}
				br.close();
			}
		}

		String[] subjects = bosphorusRoot.list();
		for (String subject : subjects) {
			File subjectDir = new File(bosphorusRoot.getAbsolutePath() + "/"
					+ subject);
			Logger.log("luxand_data_creator",
					"opening " + subjectDir.getAbsolutePath());
			if (subjectDir.isDirectory()) {
				String[] files = subjectDir.list();
				Arrays.sort(files);

				// output file - check if exists, create if necessary and
				// load already existing content
				if (!withLabels) {
					processed = new ArrayList<String>();
					output = new File(subjectDir.getAbsoluteFile() + "/"
							+ output_file_name);
					if (output.exists()) {
						BufferedReader br = new BufferedReader(new FileReader(
								output));
						String line;
						while ((line = br.readLine()) != null) {
							if (line.split(":").length > 1)
								processed.add(line.split(":")[0]);
						}
						br.close();
					}
				}

				for (String file : files) {
					if ((file.contains(".png") || file.contains(".jpg"))
							&& !processed.contains(file)
							&& !processedWithError(file)) {
						// there is a loop but each img is added once:
						// either generally without label, or for the only
						// label it has
						for (Label l : AU.Label.values()) {
							String label = l.toString();
							if (!withLabels || file.contains(label)) {
								Photo photo = new Photo(
										subjectDir.getAbsolutePath() + "/"
												+ file);
								photo.generateFeatures();
								try {
									Utils.writeFile(
											output,
											file + ":"
													+ photo.featuresToString()
													+ (withLabels ? label : ""));
									Logger.log("luxand_data_creator", ++imgDone
											+ ": " + file);
									processed.add(file);
								} catch (Exception e) {
									Logger.log("luxand_data_creator",
											"ERROR: cannot process image "
													+ file);
								}
							}
							// do not add each image Label.values().size()
							// times when labels are not considered
							if (!withLabels)
								break;
						}
					} else if (processed.contains(file)) {
						Logger.log("luxand_data_creator", ++imgDone + ": "
								+ file + " - skipping");
					}
				}
			}
		}
	}

	private static boolean processedWithError(String file) {
		String cmd = "sh processed_with_error.sh " + file;
		String res = Utils.runCmd(cmd);
		try {
			if (Integer.valueOf(res.trim()) > 0)
				return true;
		} catch (Exception e) {
			Logger.log("luxand_data_creator", "new file: " + file);
		}
		return false;
	}

	public static void divideLuxandData(String luxand_data_file)
			throws IOException {

		BufferedReader br;
		String line;

		File trainFile = new File(luxand_data_file + "_train_data");
		File testFile = new File(luxand_data_file + "_test_data");

		if (!trainFile.exists())
			trainFile.createNewFile();
		if (!testFile.exists())
			testFile.createNewFile();

		for (Label label : AU.Label.values()) {
			File input = new File(luxand_data_file);
			br = new BufferedReader(new FileReader(input));
			int rowsByLabel = 0;
			while ((line = br.readLine()) != null)
				if (line.split(":")[2].equals(label.toString()))
					rowsByLabel++;

			br.close();
			br = new BufferedReader(new FileReader(input));
			int processed = 0;
			while ((line = br.readLine()) != null) {
				if (line.split(":")[2].equals(label.toString())) {
					if (processed < rowsByLabel * 0.8)
						Utils.writeFile(trainFile, line);
					else
						Utils.writeFile(testFile, line);
					processed++;
				}
			}
			br.close();

		}

	}
}
